package org.ibase4j.core.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;

import javax.imageio.ImageIO;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.impl.code39.Code39Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;

/**
 * 条码、二维码工具类
 * @author manu-team
 *
 */
public class BarcodeUtil {
	private static Logger logger = LogManager.getLogger();
	private static int DEFAULT_QR_WIDTH = 300;
	private static int DEFAULT_QR_HEIGHT = 300;
	private static int DEFAULT_BAR_WIDTH = 300;
	private static int DEFAULT_BAR_HEIGHT = 100;
	private static String DEFAULT_CHARACTER_SET = "UTF-8";
	private static String DEFAULT_PIC_TYPE = "png";

	/**
	 * 生成128条码图片
	 * @param dir 图片存放路径
	 * @param content 条码内容
	 * @return
	 */
	public static String createBarcode(String dir, String content) {
		return createBarcode(dir, content, DEFAULT_BAR_WIDTH, DEFAULT_BAR_HEIGHT);
	}
	
    /**
     * 显示条形的内容
     * @param bCBitmap 已生成的条形码的位图
     * @param content  条形码包含的内容
     * @return 返回生成的新位图,它是 方法{@link #createQRCode(String, int, int, Bitmap)}返回的位图与新绘制文本content的组合
     */
//    private static BinaryBitmap showContent(BinaryBitmap bCBitmap , String content){
//        if (TextUtils.isEmpty(content) || null == bCBitmap){
//            return null;
//        }
//        Paint paint = new Paint();
//        paint.setColor(Color.BLACK);
//        paint.setAntiAlias(true);
//        paint.setStyle(Paint.Style.FILL);//设置填充样式
//        paint.setTextSize(20);
////        paint.setTextAlign(Paint.Align.CENTER);
//        //测量字符串的宽度
//        int textWidth = (int) paint.measureText(content);
//        Paint.FontMetrics fm = paint.getFontMetrics();
//        //绘制字符串矩形区域的高度
//        int textHeight = (int) (fm.bottom - fm.top);
//        // x 轴的缩放比率
//        float scaleRateX = bCBitmap.getWidth() / textWidth;
//        paint.setTextScaleX(scaleRateX);
//        //绘制文本的基线
//        int baseLine = bCBitmap.getHeight() + textHeight;
//        //创建一个图层，然后在这个图层上绘制bCBitmap、content
//        BinaryBitmap  bitmap = BinaryBitmap.createBitmap(bCBitmap.getWidth(),bCBitmap.getHeight() + 2 * textHeight,BinaryBitmap.Config.ARGB_4444);
//        Canvas canvas = new Canvas();
//        canvas.drawColor(Color.WHITE);
//        canvas.setBitmap(bitmap);
//        canvas.drawBitmap(bCBitmap, 0, 0, null);
//        canvas.drawText(content,bCBitmap.getWidth() / 10,baseLine,paint);
//        canvas.save(Canvas.ALL_SAVE_FLAG);
//        canvas.restore();
//        return bitmap;
//    }
	
	/**
	 * 生成128条码图片
	 * @param dir 图片存放路径
	 * @param content 条码内容
     * @param width 图片宽度
     * @param height 图片高度
	 * @return
	 */
	public static String createBarcode1(String dir, String content, int width, int height) {
		// 文字编码 
		HashMap<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>(); 
        hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHARACTER_SET); 

        try {
	        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.CODE_128, width, height, hints);
	        File file = new File(dir, "B-" + content + "." + DEFAULT_PIC_TYPE);
	        MatrixToImageWriter.writeToPath(bitMatrix, DEFAULT_PIC_TYPE, file.toPath());
	        return file.getAbsolutePath();
        } catch (Exception e) {
            logger.error("", e);
        }
        return "";
	}
	
	
	public static String createBarcode2(String dir, String content, int width, int height){
		//Create the barcode bean
        Code39Bean bean = new Code39Bean();

        final int dpi = 150;

        //Configure the barcode generator
        bean.setModuleWidth(UnitConv.in2mm(1.0f / dpi)); //makes the narrow bar 
                                                         //width exactly one pixel
        bean.setWideFactor(5);
        bean.doQuietZone(true);
        bean.setQuietZone(2);

        //Open output file
        File outputFile = new File(dir, "B-" + content + "." + DEFAULT_PIC_TYPE);
        OutputStream out = null;
        try {
        	out = new FileOutputStream(outputFile);
            //Set up the canvas provider for monochrome JPEG output 
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(
                    out, "image/png", dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);

            //Generate the barcode
            bean.generateBarcode(canvas, content);

            //Signal end of generation
            canvas.finish();
            out.close();
        } catch (Exception e) {
            logger.error("", e);
        } finally {
			try {
				if(out != null) {
					out.close();
				}
			}catch (IOException e) {
				logger.error("", e);
			}
		}
        return outputFile.getAbsolutePath();
	}
	
	public static String createBarcode(String dir, String content, int width, int height){
		//Create the barcode bean
        Code128Bean bean = new Code128Bean();

        final int dpi = 150;

        //Configure the barcode generator
        bean.setModuleWidth(UnitConv.in2mm(2.0f / dpi)); //makes the narrow bar 
                                                         //width exactly one pixel
//        bean.setWideFactor(5);
//        bean.setModuleWidth(width/dpi);
        bean.setHeight(20);
        bean.doQuietZone(true);	
        bean.setQuietZone(2);	//两边空白区

        //Open output file
        File outputFile = new File(dir, "B-" + content + "." + DEFAULT_PIC_TYPE);
        OutputStream out = null;
        try {
        	out = new FileOutputStream(outputFile);
            //Set up the canvas provider for monochrome JPEG output 
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(
                    out, "image/png", dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);

            //Generate the barcode
            bean.generateBarcode(canvas, content);

            //Signal end of generation
            canvas.finish();
            out.close();
        } catch (Exception e) {
            logger.error("", e);
        } finally {
			try {
				if(out != null) {
					out.close();
				}
			}catch (IOException e) {
				logger.error("", e);
			}
		}
        return outputFile.getAbsolutePath();
	}
	
	/**
	 * 生成二维码图片
	 * @param dir 图片存放路径
	 * @param content 二维码内容
	 * @return
	 */
    public static String createQrcode(String dir, String content) {
        return createQrcode(dir, content, DEFAULT_QR_WIDTH, DEFAULT_QR_HEIGHT);
    }

    /**
     * 生成二维码图片
     * @param dir 图片存放路径
     * @param content 二维码内容
     * @param width 图片宽度
     * @param height 图片高度
     * @return
     */
    public static String createQrcode(String dir, String content, int width, int height) {
        try {
            HashMap<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();
            hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHARACTER_SET);
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);

            File file = new File(dir, "Q-" + content + "." + DEFAULT_PIC_TYPE);
            MatrixToImageWriter.writeToPath(bitMatrix, DEFAULT_PIC_TYPE, file.toPath());
            return file.getAbsolutePath();
        } catch (Exception e) {
            logger.error("", e);
        }
        return "";
    }

    /**
     * 二维码图片解码
     * @param filePath
     * @return
     */
    public static String decodeQr(String filePath) {
        String retStr = "";
        if ("".equalsIgnoreCase(filePath) && filePath.length() == 0) {
            return "图片路径为空!";
        }
        try {
            BufferedImage bufferedImage = ImageIO.read(new FileInputStream(filePath));
            LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap bitmap = new BinaryBitmap(binarizer);
            HashMap<DecodeHintType, Object> hintTypeObjectHashMap = new HashMap<>();
            hintTypeObjectHashMap.put(DecodeHintType.CHARACTER_SET, DEFAULT_CHARACTER_SET);
            Result result = new MultiFormatReader().decode(bitmap, hintTypeObjectHashMap);
            retStr = result.getText();
        } catch (Exception e) {
            logger.error("", e);
        }
        return retStr;
    }
    
    public static void main(String[] args) {
		String dir = "D:\\output";
		String content = "O-000002";
		BarcodeUtil.createBarcode(dir, content);
//		BarcodeUtil.createQrcode(dir, content);
	}
}
